<template>
  <div id="container"
       ref="container"
       :style="containerStyle"
       @pointerdown="containerMouseDown"
       @mouseup="cursorState=cursorState=='brush'?'brush':null">
    <slide-zoom-viewer v-if="zoomImage.isZoom" :disable="expandScreen"/>
    <!-- 播放遮罩层 -->
    <mask-canvas v-if="isShowMask"
                 :isDraw="maskCanvas.isDraw && !expandScreen"
                 :brushColor="defaultBrush.color"
                 :brushWidth="defaultBrush.width"
                 :zoomMultiples="defaultZoomMultiples"
                 :drawMode="maskCanvas.drawMode"
                 :containerSize="{width:containerWidth,height:containerHeight}"
                 :trajectorys="maskCanvas.trajectorys"
                 :zoomLocation="maskCanvas.zoomImage.location"
                 :imageFile="maskCanvas.zoomImage.url"
                 @DrawTrajectoryed="!expandScreen?setMaskTrajectory($event):null"
                 @InflateRect="!expandScreen?setMaskZoomLocation($event):null"
                 @Click="nextAnimation"/>
    <!-- 图片查看 -->
    <!-- <keep-alive> -->
    <slide-picture-viewer ref="imageViewer"
                          :brushColor="defaultBrush.color"
                          :brushWidth="defaultBrush.width"
                          :zoomMultiples="defaultZoomMultiples"
                          :containerSize="{width:containerWidth,height:containerHeight}"
                          :imageFiles="temporaryFile.files" :texts="temporaryFile.texts"
                          :trajectorys="temporaryFile.trajectorys"
                          :zoomImage="temporaryFile.zoomImage"
                          :scroll="temporaryFile.scroll"
                          :isFill="isShowCover"
                          :expandScreen="expandScreen"
                          :isDraw="temporaryFile.isDraw && !expandScreen"
                          :isZoom="temporaryFile.isZoom"
                          v-if="isPlay && temporaryFile.files.length"
                          @scroll="setTemporaryScroll"
                          @DrawTrajectoryed="setTemporaryTrajectory"
                          @ImageLoaded="setTemporaryFileSize"
                          @ZoomStateChanged="setTemporaryZoomImage($event)"
                          @InflateRect="setTemporaryZoomLocation($event)"/>
    <!-- </keep-alive> -->
    <!-- 图片裁剪 -->
    <!-- :Selected="element." -->
    <slide-image-resizer
      v-if="isCropImage"
      :image="cropImage"
      :sign-style="$store.state.slideEditor.customized.DefaultGraphStyle"
      @FinishCropImg="addCropImage"
      @replaceCropImg="replaceCropImg"
    />
    <slide-element :ref="'el_'+element.id"
                   :ID="element.id"
                   :Title="element.text || element.html"
                   :Location="{ top: element.top, left: element.left }"
                   :Size="getElementSize(element)"
                   :ElementStyle="{ border: '1px dashed #999'}"
                   :Activated="activeElement && activeElement.id==element.id"
                   :ContainerSize="{width:containerWidth,height:containerHeight}"
                   :LockWidth="element.lockWidth"
                   :LockHeight="element.type=='STRAGHTLINE'?true:element.lockHeight"
                   :LockMove="element.lockMove || element.isEdit || element.templateElement"
                   :LockSelect="element.lockSelect"
                   :ContextMenu="contextMenu"
                   :isShowSaveLocal="element.type=='IMAGE'"
                   v-if="element.show"
                   v-for="(element,index) in elements"
                   :key="index"
                   @Click="setActiveElement(element)"
                   @LocSizeChanging="elLocAndSizeChanging"
                   @SlideElementFinish="slideElementFinish"
                   @appended="appended"
                   @Copy="CopyElement"
                   @Progress="GoNextEditState"
                   @Fallback="GoBackEditState"
                   @Delete="delActiveElement"
                   @PreviousLayer="PreviousLayer"
                   @NextLayer="NextLayer"
                   @TopLayer="TopLayer"
                   @UnderLayer="UnderLayer"
                   @FullSreen="FullSreen">
      <!-- 文本框 -->
      <slide-text :ref="element.id" v-if="element.type=='TEXT'"
                  :ID="element.id"
                  :HtmlValue="element.html"
                  :TextValue="element.text"
                  :isReadonly="element.templateElement || isPlay"
                  :isEdit="element.isEdit"
                  :isConvertImg="expandScreen"
                  :containerStyle="getElementContentStyle(element)"
                  @TextChangeFinish="TextChanged"/>
      <!-- 图片 -->
      <slide-image :ref="element.id" v-if="element.type=='IMAGE'" :ID="element.id" :FileCode="element.fileCode"
                   :FilePath="element.path" :isReadonly="element.templateElement || isPlay"
                   :containerStyle="getElementContentStyle(element)" :zoom="element.zoom"
                   @ImageLoadFinish="ImageLoadFinish"/>
      <!-- 视频 -->
      <slide-media :ref="element.id" v-if="element.type=='MEDIA'" :ID="element.id" :FileCode="element.fileCode"
                   :FilePath="element.path" :isReadonly="element.templateElement || isPlay"
                   :containerStyle="getElementContentStyle(element)" :isShowToolBar="!expandScreen"
                   :isPlayVolume="expandScreen" :isAutoPlay="false" :isPlayFile="getMediaFileState()"
                   @MediaLoadFinish="MediaOrAudioLoadFinish"/>
      <!-- 音频 -->
      <slide-audio :ref="element.id" v-if="element.type=='AUDIO'" :ID="element.id" :FileCode="element.fileCode"
                   :FilePath="element.path" :isReadonly="element.templateElement || isPlay"
                   :containerStyle="getElementContentStyle(element)" :isShowToolBar="!expandScreen"
                   :isPlayVolume="expandScreen" :isAutoPlay="false"
                   :containerSize="{width:element.width,height:element.height}" :isPlayFile="getMediaFileState()"
                   @AudioLoadFinish="MediaOrAudioLoadFinish"/>
      <!-- 直线 -->
      <slide-straight-line :ref="element.id" v-if="element.type=='STRAGHTLINE'"
                           :containerSize="{width:element.width,height:element.height/2}"
                           :containerStyle="getElementContentStyle(element)"/>
      <!-- 矩形 -->
      <slide-rectangle :ref="element.id" v-if="element.type=='RECTANGLE'"
                       :containerSize="{width:element.width,height:element.height}"
                       :containerStyle="getElementContentStyle(element)"/>
      <!-- 椭圆 -->
      <slide-ellipse :ref="element.id" v-if="element.type=='ELLIPSE'"
                     :containerSize="{width:element.width,height:element.height}"
                     :containerStyle="getElementContentStyle(element)"/>
      <!-- 文档 -->
      <slide-document :ref="element.id" v-if="element.type=='DOCUMENT'" :ID="element.id"
                      :isReadonly="element.templateElement || isPlay"
                      :containerStyle="getElementContentStyle(element)"/>
    </slide-element>
    <editor-context-menu :ContextMenu="contextMenu"
                         @Paste="PasteElement"
    ></editor-context-menu>
  </div>
</template>
<script>
  import uuid from 'uuid/v4'
  import {mapState, mapActions, mapGetters} from 'vuex'
  import MaskCanvas from './SlideEditor/MaskCanvas'
  import SlideZoomViewer from './SlideEditor/SlideZoomViewer'
  import SlidePictureViewer from './SlideEditor/SlidePictureViewer'
  import SlideImageResizer from './SlideEditor/SlideImageResizer'
  import SlideElement from './SlideEditor/SlideElement'
  import Ellipse from './SlideEditor/Ellipse'
  import Rectangle from './SlideEditor/Rectangle'
  import StraightLine from './SlideEditor/StraightLine'
  import Text from './SlideEditor/Text'
  import Image from './SlideEditor/Image'
  import Media from './SlideEditor/Media'
  import Audio from './SlideEditor/Audio'
  import EditorContextMenu from './SlideEditor/EditorContextMenu'
  import Document from './SlideEditor/Document'
  import action from '../common/typeActions'
  import ipcs from '../common/typeIpcs'
  import editorServer from '../server/slideEditor/editorServer'

  const ResizeSensor = require('css-element-queries/src/ResizeSensor')

  let remote = ''
  let screen = ''

  export default {
    name: 'SlideEditor',
    data () {
      return {
        editEls: null,
        isDomListening: false,
        contextMenu: [
          {
            id: 'Paste',
            icon: (process.browser ? '/static' : remote.getGlobal('staticPath')) + '/img/zt.png',
            text: '粘贴',
            event: 'Paste',
            disable: true,
            show: true
          }
        ],
        containerSize: {width: 0, height: 0},
        containerWidth: 0, // 容器宽度
        containerHeight: 0, // 容器高度
        useCursor: 'default', // defualt,pointer,crosshair
        clickLocation: null, // 鼠标左键按下时上坐标
        cropImage: null
      }
    },
    components: {
      'mask-canvas': MaskCanvas,
      'slide-zoom-viewer': SlideZoomViewer,
      'slide-picture-viewer': SlidePictureViewer,
      'slide-image-resizer': SlideImageResizer,
      'slide-element': SlideElement,
      'slide-ellipse': Ellipse,
      'slide-rectangle': Rectangle,
      'slide-straight-line': StraightLine,
      'slide-text': Text,
      'slide-image': Image,
      'slide-media': Media,
      'slide-audio': Audio,
      EditorContextMenu,
      'slide-document': Document
    },
    created: function () {
      this.$eventBus.$off('keydown')
      this.$eventBus.$off('keyup')
      this.$eventBus.$off('pointerdown')
      this.$eventBus.$off('pointerup')
    },
    props: {
      expandScreen: {type: Boolean, default: true}
    },
    mounted: async function () {
      let self = this
      if (screen) {
        // 连接多屏
        screen.on('display-added', () => {
          if (!self.isPlay) return
          self.$electron.ipcRenderer.send(ipcs.MAIN.openExpandScreen, {
            id: 'SlideExpandScreen',
            URL: 'SlideEditor',
            State: self.state
          })
        })

        // 移除多屏
        screen.on('display-removed', () => {
          self.$electron.ipcRenderer.send(ipcs.MAIN.closeExpandScreen)
        })
      }
      let containerSize = self.$route.query.containerSize // 获取url地址中的参数
      // 初始化容器大小
      self.$nextTick(function () {
        // 当未获取到容器大小时获取窗体大小
        if (containerSize) {
          containerSize = JSON.parse(containerSize)
          self.calContainerSize(containerSize.width, containerSize.height - 2)
        } else {
          let container = self.$refs.container
          self.calContainerSize(container.clientWidth, container.clientHeight)
        }
      })

      // 当在扩展屏幕显示时，订阅状态更新事件
      if (self.expandScreen) {
        // 订阅state状态同步
        if (self.$electron) {
          self.$electron.ipcRenderer.on(ipcs.RENDERER.dataSync, (event, arg) => {
            arg.State.expandScreen = true
            self.$store.dispatch(action.SLIDEEDITOR.SetState, arg.State)
          })
        }
      } else {
        // 记录幻灯片状态
        self.$eventBus.$on('pointerdown', () => {
          self.editEls = JSON.stringify(self.elements)
        })
        self.$eventBus.$on('keydown', () => {
          if ([37, 38, 39, 40, 46].indexOf(event.keyCode) === -1 || !(event.ctrlKey && event.keyCode === 86) || !(event.ctrlKey && event.keyCode === 90) || self.editEls) return
          self.editEls = JSON.stringify(this.elements)
        })
        self.$eventBus.$on('pointerup', self.addEditState)
        self.$eventBus.$on('keyup', this.documentKeyUp)
        self.$eventBus.$on('keyup', this.laserPointerOperation)
        if (self.$electron) {
          // 程序退出时关闭扩展屏
          self.$electron.ipcRenderer.on('beforeClose', async (ev, args) => {
            await self.$store.dispatch(action.SLIDEEDITOR.SaveSlideElement)
          })
        }
      }
    },
    beforeDestroy: async function () {
      // 组件销毁时注销事件，自动保存
      this.$eventBus.$off('keyup', this.documentKeyUp)
      this.$eventBus.$off('keyup', this.laserPointerOperation)
      await this.$store.dispatch(action.SLIDEEDITOR.SaveSlideElement)
    },
    watch: {
      isPlay: function () {
        this.cursorState = null
      },
      containerScale: function (n, o) {
        this.calContainerSize(
          this.containerSize.width,
          this.containerSize.height
        )
      },
      isCropImage: async function (n, o) {
        if (!n) {
          this.cropImage = null
          return
        }
        // 选中图片时，裁剪选中图片，否则裁剪整个幻灯片区域
        if (
          this.activeElement &&
          this.activeElement.type === 'IMAGE' &&
          this.activeElement.path
        ) {
          this.cropImage = this.getFilePath(this.activeElement.path)
        } else {
          this.cropImage = await this.cropEditorArea()
        }
      },
      'maskCanvas.isZoom': async function (n, o) {
        if (this.expandScreen) return
        // 监视播放时幻灯片缩放状态
        this.setMaskZoomImage(n ? await this.cropEditorArea() : null)
      },
      cursorState: function (n, o) {
        if (n === 'addElement') {
          this.useCursor = 'crosshair'
        } else if (n === 'brush') {
          this.useCursor = 'crosshair'
        } else {
          this.useCursor = 'default'
        }
      },
      copyElement: function (n, o) {
        this.contextMenu.forEach(item => {
          if (['Paste'].indexOf(item.id) >= 0) {
            item.disable = !n
          }
        })
      }
    },
    // 计算表达式
    computed: {
      // 获取幻灯片元素
      ...mapState({
        state: state => state.slideEditor,
        isEditState: state => state.slideEditor.isEditState,
        isPlay: state => state.slideEditor.isPlay,
        autoPlay: state => state.slideEditor.autoPlay,
        preview: state => state.slideEditor.preview,
        containerScale: state => state.slideEditor.customized.ContainerScale,
        slideFiles: state => state.slideEditor.files,
        temporaryFile: state => state.slideEditor.temporaryFile,
        copyElement: state => state.slideEditor.copyElement,
        isCropImage: state => state.slideEditor.isCropImage,
        isShowCover: state => state.slideEditor.isShowCover,
        maskCanvas: state => state.slideEditor.maskCanvas,
        isZoomEditor: state => state.slideEditor.isZoomEditor,
        defaultZoomMultiples: state =>
          state.slideEditor.customized.DefaultZoomMultiples,
        defaultBrush: state => state.slideEditor.customized.DefaultBrush,
        zoomImage: state => state.slideEditor.zoomImage
      }),
      ...mapGetters(['elements', 'getFilePath', 'backgroundImage']),
      // 活动元素
      activeElement: {
        get () {
          return this.$store.state.slideEditor.activeElement
        },
        set (el) {
          this.$store.dispatch(action.SLIDEEDITOR.SetActiveElement, el)
        }
      },
      // 鼠标状态
      cursorState: {
        get () {
          return this.$store.state.slideEditor.cursorState
        },
        set (value) {
          this.$store.dispatch(action.SLIDEEDITOR.SetCursorState, value)
        }
      },
      // 容器样式
      containerStyle: function () {
        try {
          if (!this.containerWidth || !this.containerWidth) return
          let style = {
            cursor: this.useCursor,
            width: this.containerWidth + 'px',
            height: this.containerHeight + 'px',
            float: 'left'
          }
          if (this.backgroundImage) {
            style['background-image'] = `url(${this.backgroundImage})`
          }

          let marginTop = this.containerSize.height - this.containerHeight
          if (marginTop) {
            style['margin-top'] = `${marginTop / 2}px`
          }
          let marginLeft = this.containerSize.width - this.containerWidth
          if (marginLeft) {
            style['margin-left'] = `${marginLeft / 2}px`
          }
          return style
        } catch (error) {
          console.error(error)
          this.$alert(error.message, '初始化容器错误', {type: 'error'})
        }
      },
      isShowMask: function () {
        if (!this.isPlay && !this.preview) return false

        return this.maskCanvas.isDraw || this.maskCanvas.isZoom
        // return !this.elements.find(el => {
        //   return el.type === 'MEDIA' || el.type === 'AUDIO'
        // })
      }
    },
    methods: {
      ...mapActions({
        // 上一动画
        previousAnimation: action.SLIDEEDITOR.PreviousAnimation,
        // 下一动画
        nextAnimation: action.SLIDEEDITOR.NextAnimation,
        // 设置封面显示状态
        setCoverState: action.SLIDEEDITOR.SetCoverState,
        // 设置播放状态
        setPlayState: action.SLIDEEDITOR.SetPlayState,
        // 设置元素属性
        setElementAttr: action.SLIDEEDITOR.SetElementAttr,
        // 设置临时文件滚动位置
        setTemporaryScroll: action.SLIDEEDITOR.SetTemporaryScroll,
        // 设置临时文件标注
        setTemporaryTrajectory: action.SLIDEEDITOR.SetTemporaryTrajectory,
        // 设置临时文件大小比例
        setTemporaryFileSize: action.SLIDEEDITOR.SetTemporaryFileSize,
        // 设置播放遮罩层标注
        setMaskTrajectory: action.SLIDEEDITOR.SetMaskTrajectory,
        // 设置遮罩缩放图片
        setMaskZoomImage: action.SLIDEEDITOR.SetMaskZoomImage,
        // 设置遮罩缩放图片位置
        setMaskZoomLocation: action.SLIDEEDITOR.SetMaskZoomLocation,
        // 设置临时投影区缩放图片
        setTemporaryZoomImage: action.SLIDEEDITOR.SetTemporaryZoomImage,
        // 设置临时投影区图片位置
        setTemporaryZoomLocation: action.SLIDEEDITOR.SetTemporaryZoomLocation,
        // 删除活动元素
        delActiveElement: action.SLIDEEDITOR.DelActiveElement,
        // 复制活动元素
        CopyElement: action.SLIDEEDITOR.CopyElement,
        // 粘贴复制元素
        PasteElement: action.SLIDEEDITOR.PasteElement,
        // 幻灯片状态前进
        GoNextEditState: action.SLIDEEDITOR.GoNextEditState,
        // 幻灯片状态撤销
        GoBackEditState: action.SLIDEEDITOR.GoBackEditState
      }),
      // 初始化容器
      initContainer: function (dom) {
        if (this.isDomListening) return
        this.calContainerSize(dom.clientWidth, dom.clientHeight)
        /* eslint-disable no-new */
        new ResizeSensor(dom, () => {
          // 监听容器大小变化，重新容器大小
          this.isDomListening = true
          this.calContainerSize(dom.clientWidth, dom.clientHeight)
        })
      },
      // 添加元素完成后执行
      appended: function (id) {
        let appendEl = {...this.elements.find(x => x.id === id)}
        if (!appendEl.id || (appendEl.width && appendEl.height)) return
        appendEl.width = 0.3
        if (appendEl.left - appendEl.width / 2 < 0) {
          appendEl.left = 0
        } else if (appendEl.left + appendEl.width / 2 > 1) {
          appendEl.left = 1 - appendEl.width
        } else {
          appendEl.left = appendEl.left - appendEl.width / 2
        }

        if (appendEl.type !== 'STRAGHTLINE') {
          appendEl.height = 0.2
          if (appendEl.top - appendEl.height / 2 < 0) {
            appendEl.top = 0
          } else if (appendEl.top + appendEl.height / 2 > 1) {
            appendEl.top = 1 - appendEl.height
          } else {
            appendEl.top = appendEl.top - appendEl.height / 2
          }
        }
        this.$store.dispatch(action.SLIDEEDITOR.SetElementAttr, [
          {id: appendEl.id, attrName: 'left', attrValue: appendEl.left},
          {id: appendEl.id, attrName: 'top', attrValue: appendEl.top},
          {id: appendEl.id, attrName: 'width', attrValue: appendEl.width},
          {id: appendEl.id, attrName: 'height', attrValue: appendEl.height}
        ])
      },
      // 上一图层
      PreviousLayer: function (id) {
        try {
          let el = this.elements.find(x => {
            return x.id === id
          })
          if (!el) return
          let els = this.elements.filter(item => {
            return !item.templateElement && item.index > el.index
          })
          if (!els.length) return
          let obj = {dragEl: el.id}

          obj.dropEl = els[0].id
          obj.exchangeType = 'after'
          this.$store.dispatch(action.SLIDEEDITOR.ExchangeLayerOrder, obj)
        } catch (error) {
          console.error(error)
          this.$alert(error.message, '错误', {type: 'error'})
        }
      },
      // 下一图层
      NextLayer: function (id) {
        try {
          let el = this.elements.find(x => {
            return x.id === id
          })
          if (!el) return
          let els = this.elements.filter(item => {
            return !item.templateElement && item.index < el.index
          })
          if (!els.length) return
          let obj = {dragEl: el.id}
          // 向上移动
          if (els.length === 1) {
            obj.dropEl = els[0].id
            obj.exchangeType = 'before'
          } else if (els.length >= 2) {
            obj.dropEl = els[els.length - 2].id
            obj.exchangeType = 'after'
          }
          this.$store.dispatch(action.SLIDEEDITOR.ExchangeLayerOrder, obj)
        } catch (error) {
          console.error(error)
          this.$alert(error.message, '错误', {type: 'error'})
        }
      },
      // 至于顶层
      TopLayer: function (id) {
        try {
          let el = this.elements.find(x => {
            return x.id === id
          })
          if (!el) return
          let els = this.elements.filter(item => {
            return !item.templateElement && item.index > el.index
          })
          if (!els.length) return
          let obj = {dragEl: el.id}

          obj.dropEl = els[els.length - 1].id
          obj.exchangeType = 'after'
          this.$store.dispatch(action.SLIDEEDITOR.ExchangeLayerOrder, obj)
        } catch (error) {
          console.error(error)
          this.$alert(error.message, '错误', {type: 'error'})
        }
      },
      // 至于底层
      UnderLayer: function (id) {
        try {
          let el = this.elements.find(x => {
            return x.id === id
          })
          if (!el) return
          let els = this.elements.filter(item => {
            return !item.templateElement && item.index < el.index
          })
          if (!els.length) return
          let obj = {dragEl: el.id}

          obj.dropEl = els[0].id
          obj.exchangeType = 'before'
          this.$store.dispatch(action.SLIDEEDITOR.ExchangeLayerOrder, obj)
        } catch (error) {
          console.error(error)
          this.$alert(error.message, '错误', {type: 'error'})
        }
      },
      // 全屏
      FullSreen: function (id) {
        this.setElementAttr([
          {id: id, attrName: 'left', attrValue: 0},
          {id: id, attrName: 'top', attrValue: 0},
          {id: id, attrName: 'width', attrValue: 1},
          {id: id, attrName: 'height', attrValue: 1}
        ])
        this.$eventBus.$emit('pointerup')
      },
      // 获取媒体文件播放状态
      getMediaFileState: function () {
        if (!this.isPlay) return false
        if (this.autoPlay === 'play') {
          return true
        } else if (this.autoPlay === 'pause') return false
        return true
      },
      slideElementFinish: function (id) {
        let el = this.$refs[id]
        el = !el || !el.length ? null : el[0]

        if (!el || !el.init || typeof el.init !== 'function') return
        el.init()
      },
      // 设置元素位置大小
      elLocAndSizeChanging: function (el) {
        if (!this.containerWidth || !this.containerHeight) return

        this.setElementAttr([
          {
            id: el.ID,
            attrName: 'width',
            attrValue: el.width / this.containerWidth
          },
          {
            id: el.ID,
            attrName: 'height',
            attrValue: el.height / this.containerHeight
          },
          {
            id: el.ID,
            attrName: 'top',
            attrValue: el.top / this.containerHeight
          },
          {
            id: el.ID,
            attrName: 'left',
            attrValue: el.left / this.containerWidth
          }
        ])
      },
      ImageLoadFinish: async function (fileInfo) {
      },
      MediaOrAudioLoadFinish: function (fileInfo) {
        this.setElementAttr({
          id: fileInfo.ID,
          attrName: 'path',
          attrValue: fileInfo.fileSource
        })
      },
      TextChanged: function (textInfo) {
        this.setElementAttr([
          {
            id: textInfo.ID,
            attrName: 'html',
            attrValue: textInfo.text
          },
          {
            id: textInfo.ID,
            attrName: 'text',
            attrValue: textInfo.text
          }
        ])
      },
      documentKeyUp: async function () {
        if (this.isPlay) return
        switch (event.keyCode) {
          // 点击Esc时取消鼠标状态
          case 27:
            if (this.cursorState !== 'normal') {
              this.cursorState = null
            } else if (this.activeElement) this.activeElement = null
            break
          // 点击Delete时删除活动元素
          case 46:
            await this.delActiveElement()
            break
          // C复制元素
          case 67:
            if (!event.ctrlKey || !this.activeElement || this.activeElement.isEdit) return
            this.CopyElement()
            break
          // V粘贴元素
          case 86:
            if (!event.ctrlKey || !this.copyElement || this.activeElement.isEdit) return
            this.PasteElement()
            break
          // Y状态前进
          case 89:
            if (!event.ctrlKey) return
            this.GoNextEditState()
            break
          // Z状态撤销
          case 90:
            if (!event.ctrlKey) return
            this.GoBackEditState()
            break
          // F5放映
          case 116:
            if (!process.browser) this.setPlayState(true)
        }
        this.addEditState()
      },
      // 激光笔操作
      laserPointerOperation: function () {
        if (
          !this.isPlay ||
          this.isZoomEditor ||
          (this.temporaryFile &&
            this.temporaryFile.files &&
            this.temporaryFile.files.length)
        ) {
          return
        }
        switch (event.keyCode) {
          // 点击Esc退出放映状态
          case 27:
            this.setPlayState(false)
            break
          case 33:
          case 37:
          case 38:
            this.previousAnimation()
            break
          case 34:
          case 39:
          case 40:
          case 91:
            this.nextAnimation()
            break
          // 显示封面
          case 190:
            this.setCoverState()
            break
        }
      },
      // 容器鼠标按下事件
      containerMouseDown: function (event) {
        if (this.isPlay || this.preview) return this.nextAnimation()
        this.clickLocation = {X: event.clientX, Y: event.clientY}
        switch (this.cursorState) {
          // 添加幻灯片元素
          case 'addElement':
            // 获取容器的浏览器坐标
            let containerLocation = this.$refs.container.getBoundingClientRect()
            // 获取鼠标点击时对于容器的坐标
            let loaction = {
              X:
                event.clientX < containerLocation.left
                  ? 0
                  : (event.clientX - containerLocation.left) /
                  this.containerWidth,
              Y:
                event.clientY < containerLocation.top
                  ? 0
                  : (event.clientY - containerLocation.top) / this.containerHeight
            }
            // 添加一个元素对象
            this.$store.dispatch(action.SLIDEEDITOR.AddActiveElement, loaction)
            this.$nextTick(function () {
              if (!this.activeElement) return
              let el = this.$refs[`el_${this.activeElement.id}`]
              if (el && el.length) {
                el[0].setDragDirection('setLowerRightCorner')
              }
            })
            break
          default:
            break
        }
      },
      // 根据选中容器比列计算容器大小
      calContainerSize: function (width, height) {
        try {
          this.containerSize = {width: width, height: height}
          switch (this.containerScale) {
            // 全屏
            case 'fullScreen':
              this.containerWidth = width
              this.containerHeight = height
              break
            case 'square':
              if (width === height) {
                this.containerWidth = this.containerHeight = width
              } else if (width > height) {
                this.containerWidth = this.containerHeight = height
              } else {
                this.containerWidth = this.containerHeight = width
              }
              break
            // 4:3
            case 'rectangle':
              if (width * (3 / 4) <= height) {
                this.containerWidth = width
                this.containerHeight = width * (3 / 4)
              } else {
                this.containerWidth = height * (4 / 3)
                this.containerHeight = height
              }
              break
            // 16:9
            case '16:9':
              if (width * (9 / 16) <= height) {
                this.containerWidth = width
                this.containerHeight = width * (9 / 16)
              } else {
                this.containerWidth = height * (16 / 9)
                this.containerHeight = height
              }
              break
          }
        } catch (error) {
          console.error(error)
          this.$alert(error.message, '初始化容器错误', {type: 'error'})
        }
      },
      // 获取元素大小
      getElementSize: function (el) {
        let size = {
          width: el.width,
          height: el.height
        }
        if (el.type === 'STRAGHTLINE') {
          size.height = `${parseInt(el.style['border-width'])}px`
        }
        return size
      },
      // 获取元素样式
      getElementContentStyle: function (element) {
        try {
          if (!this.containerWidth || !this.containerHeight) return
          let style = {...element.style}

          style.width = `${element.width * this.containerWidth}px`
          style.height = `${element.height * this.containerHeight}px`
          // 删除边距
          delete style['margin-left']
          delete style['margin-top']

          // 放映时播放动画
          if (
            (this.isPlay || this.preview) &&
            element.animation &&
            element.animation.length
          ) {
            let playAnimation = element.animation
              .filter(x => {
                return x.isPlay === true
              })
              .sort((x, y) => {
                return x.order > y.order
              })

            style['animation'] =
              playAnimation.length > 0 ? playAnimation[0].name : null
            style['animation-duration'] =
              playAnimation.length > 0 ? playAnimation[0].time : null
          } else {
            delete style['animation']
            delete style['animation-duration']
          }
          return style
        } catch (error) {
          console.error(error)
          this.$alert(error.message, '初始化元素样式错误', {type: 'error'})
        }
      },

      // 设置活动元素
      setActiveElement: function (element) {
        try {
          if (this.isPlay) return
          // 当元素被锁定选中时终止操作
          if (element && (element.lockSelect || element.templateElement)) {
            this.activeElement = null
            return
          }
          // 选中元素和活动元素相同时终止操作
          if (
            this.activeElement &&
            element &&
            this.activeElement.id === element.id
          ) {
            return
          }

          // 获取活动元素
          // let activeElement = this.activeElement ? this.$refs[this.activeElement.id] : null
          // activeElement = activeElement && activeElement.length > 0 ? activeElement[0] : activeElement
          // 获取选中元素
          let selectElement = element ? this.$refs[element.id] : element
          selectElement =
            selectElement && selectElement.length > 0
              ? selectElement[0]
              : selectElement

          if (!selectElement) {
            this.activeElement = null
            return
          }
          this.activeElement = element
        } catch (error) {
          console.error(error)
          this.$alert(error.message, '选中元素错误', {type: 'error'})
        }
      },
      // -----------------------------------------------------------------------------------
      // 截取编辑器
      addCropImage: async function (img) {
        try {
          let container = this.$refs.container
          if (!container) return
          if (!img || !img.url) throw new Error('获取裁剪图片失败')

          let width = img.width / container.clientWidth
          let height = img.height / container.clientHeight
          width = width > 1 ? 1 : width
          height = height > 1 ? 1 : height
          let id = uuid()
          let param = {
            fileID: id,
            ID: id,
            IMG: img.url
          }
          await editorServer.addImageStream(param)

          this.$store.dispatch(action.SLIDEEDITOR.AddDossierFile, [
            {ID: param.ID, IMG: param.IMG}
          ])
          this.$store.dispatch(action.SLIDEEDITOR.AddSlideElements, {
            type: 'IMAGE',
            orientation: 'left',
            distance: 0.05,
            animation: {
              id: 'a688b505-6ff1-4d5e-9b02-90f5889e7db5',
              value: 'zoomIn'
            },
            size: {width: width, height: height},
            html: '',
            text: '',
            fileID: param.fileID,
            path: param.ID
          })
          this.$store.dispatch(action.SLIDEEDITOR.SetSlideAttr, {
            attrName: 'isCropImage',
            attrValue: false
          })

          this.$eventBus.$emit('pointerup')
        } catch (error) {
          this.$alert(error.message, '提示', {type: 'warning'})
        }
      },
      replaceCropImg: async function (img) {
        try {
          if (!img) throw new Error('获取裁剪图片失败')
          let id = uuid()
          let param = {
            fileID: id,
            ID: id,
            IMG: img
          }
          await editorServer.addImageStream(param)

          this.$store.dispatch(action.SLIDEEDITOR.AddDossierFile, [
            {ID: param.ID, IMG: param.IMG}
          ])
          this.$store.dispatch(action.SLIDEEDITOR.SetActiveElementAttr, {attrName: 'path', attrValue: param.ID})
          this.$store.dispatch(action.SLIDEEDITOR.SetActiveElementAttr, {attrName: 'fileCode', attrValue: param.ID})

          this.$store.dispatch(action.SLIDEEDITOR.SetSlideAttr, {
            attrName: 'isCropImage',
            attrValue: false
          })

          this.$eventBus.$emit('pointerup')
        } catch (error) {
          this.$alert(error.message, '提示', {type: 'warning'})
        }
      },
      // 裁剪编辑区
      cropEditorArea: function () {
        if (!remote) return null
        let self = this
        return new Promise((resolve, reject) => {
          let container = self.$refs.container
          if (!container) return
          remote.getCurrentWindow().capturePage(
            {
              x: parseInt(container.getBoundingClientRect().left),
              y: parseInt(container.getBoundingClientRect().top),
              width: container.offsetWidth,
              height: container.offsetHeight
            },
            img => {
              resolve(img.toDataURL())
            }
          )
        })
      },
      // 添加操作状态
      addEditState: function () {
        if (this.isPlay || (!this.isPlay && !this.isEditState) || !this.editEls) return
        this.$store.dispatch(action.SLIDEEDITOR.AddFallbackState, this.editEls)
        this.editEls = null
      }
    }
  }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  body {
    margin: 0;
  }

  .elcontainer_img {
    position: absolute;
    top: 0;
    left: 0;
    height: calc(100% - 32px);
  }

  /* -------------------------------------------------------- */

  .elcontainer_bg {
    background: url("~@/assets/img/SlideEditor/audio_bg.jpg");
    background-size: 100% 100%;
    position: relative;
  }

  #container {
    width: 100%;
    height: 100%;
    margin: 0px auto;
    user-select: none;
    position: relative;
    overflow-y: hidden;
    overflow-x: hidden;
    /* background-color: #d5d5d5; */
    background: url("~@/assets/img/SlideEditor/container.jpg");
    background-size: 100% 100%;
  }

  #container #masklayer {
    z-index: 99;
    position: absolute;
    background-color: rgba(255, 255, 255, 0);
    width: 100%;
    height: 100%;
  }

  .element {
    text-align: left;
    position: absolute;
  }

  .elcontainer {
    width: 100%;
    height: 100%;
  }

  .select {
    float: left;
    margin: 100px;
    border: 1px dashed #999;
    position: relative;
  }
</style>
